#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/wait.h>

#define DEFAULT_STRLEN 100
#define MAX_CMD 5

typedef struct{
	char* binpath;
	char* prog;
	char** args;
}command;

char* pathlist[DEFAULT_STRLEN];
void login(char* username)
{
        char* pw = malloc(DEFAULT_STRLEN * sizeof(char));
	fputs("Username: ", stdout);
        fflush(stdout);
        fgets(username, sizeof(username), stdin);
	username[strlen(username)-1] = '\0';
        pw = getpass("Password: ");
	fflush(stdout);
	free(pw);
	pw = NULL;
}

void prompt (char* username)
{
	printf("%s@ecsshell:~$ ", username);
	fflush(stdout);
}

void get_path()
{

	char* path = getenv("PATH");
        bzero(pathlist,sizeof(pathlist));
        int i;
        pathlist[0] = strtok(path,":");
        for (i=1;;i++)
        {
             pathlist[i]=strtok(NULL,":");
             if (pathlist[i]==NULL) break;
        }
}

char* parse_cmd (char* full_cmd,command* cmdlist,int* numcmd)
{
	char* rc;
	fgets(full_cmd,DEFAULT_STRLEN,stdin);
	if(strncmp(full_cmd,"\n",1)==0)
	{
		rc = "enter";
		return rc;
	}
        if(strncmp(full_cmd,"exit",4)==0) 
	{
		rc = "exit";
		return rc;
	}

        full_cmd[strlen(full_cmd)-1]=' ';
        int i;
        int num_args = 0;
        for(i=0;i<strlen(full_cmd);i++)
        {
             if(full_cmd[i]==' ') num_args++;
        }
//	printf ("num_args=%d\n",num_args);
	int num_then = 0;
	char* stok[200];
	memset(stok,0,200);
	stok[0] = strtok (full_cmd,"' '");
	int z;
	for (z=1;z<num_args;z++)
	{
		stok[z] = strtok(NULL,"' '");
//		printf("stok[%d]=%s\n",z,stok[z]);
		if (strncmp(stok[z],"then",4)==0)
		{
			num_then++;
		}
	}
//	printf ("num_then = %d\n",num_then);
        int j,n,m;
	m=0;
	for (j=0;j<=num_then;j++)
	{
		cmdlist[j].prog =(char*) malloc (sizeof(char)*DEFAULT_STRLEN); 
                cmdlist[j].args = (char**) malloc (sizeof(char*)*DEFAULT_STRLEN);
	//	printf("m=%d\n",m);
		if (stok[m]==NULL) break;
//		printf("stok[m]=%s\n",stok[m]);
		cmdlist[j].prog = cmdlist[j].args[0] = stok[m++];
//		printf("cmdlist[%d].prog = %s\n",j, cmdlist[j].prog);
			for (n=1;stok[m]!=NULL;n++)
			{
				if (strncmp(stok[m],"then",4)==0)
				{
					m++;
					 break;
				}
//				printf("m=%d\n",m);
				cmdlist[j].args[n] = stok[m++];
//				printf("cmdlist[%d].args[%d]=%s\n",j,n,cmdlist[j].args[n]);
			}
	}
	
	rc = "normal";
	*numcmd = num_then+1;
	return rc;
}

void create_full_path(char* exec_path, int i, command* command)
{
        strncpy(exec_path,pathlist[i],strlen(pathlist[i]));
        strncat(exec_path,"/",strlen(pathlist[i]));
	strncat(exec_path,command->prog,strlen(pathlist[i])+strlen(command->prog));
}

int exec_bin(int* escape, command* cmdlist,int numcmd)
{
	int i,k;
        int cmd_found = 0;
	
	for (k=0;k<numcmd;k++)
	{
		printf("cmdlist[%d]=%s\n",k,cmdlist[k].prog);
		for (i=0;pathlist[i]!=NULL;i++)
		{
			int numchar = (int)strlen(pathlist[i])+(int)strlen(cmdlist[k].prog)+1;
			char* exec_path = (char*)calloc(numchar,sizeof(char));
			if (exec_path == NULL) 
			{
				printf("Failed to calloc exec_path.\n");
				return 1;
			}
			create_full_path(exec_path,i,&cmdlist[k]);
			if (access(exec_path,F_OK|X_OK)!=-1)
			{	
				printf("exec_path = %s.\n",exec_path);
				cmd_found = 1;
				if (fork()==0)
				{
					if (execv(exec_path,cmdlist[k].args)==-1)
					{
						printf("Ouch! execv() failed!\n");
						*escape = 1;
						break;
					}
					
				}
				else
				{
					wait(NULL);
					free(exec_path);
					break;
				}
			}

			free(exec_path);
		}
	}
	return cmd_found;
}


int main(int argc, char* argv[])
{
	time_t current;
	time(&current);
	printf("%s",ctime(&current));
	char* username  = malloc(DEFAULT_STRLEN * sizeof(char));
	login(username);
	int cmd_found = 0;
	int escape = 0;
	command cmdlist[MAX_CMD];
        fflush(stdout);
	get_path();
	while(1)
	{
		prompt(username);
		char* full_cmd = (char*) malloc(DEFAULT_STRLEN);
		char* rc;
		int numcmd =0;
		rc = parse_cmd (full_cmd,cmdlist,&numcmd);
//		printf("numcmd=%d\n",numcmd);
		if (strncmp(rc,"exit",strlen(rc))==0) break;
		else if (strncmp(rc,"enter",strlen(rc))==0) continue;

		cmd_found = exec_bin(&escape,cmdlist,numcmd);
		free(full_cmd);
		if (escape ==1)
		{
			printf("OUCH!\n");
			return 0;
		}
		if (cmd_found == 0)
		 	printf("Command not found.\n");	
	/*char* cwd;
	long path_size;
	path_size = pathconf(".", _PC_PATH_MAX);
	cwd = (char*) malloc(path_size);
	getcwd (cwd,(size_t) path_size);
	printf("path = %s\n",cwd);*/
	}
	free(username);
	return 0;
}


